package thread;

import java.util.Scanner;

public class Demo18 {
    //内存可见性问题
    //这个是 线程安全的问题之一

    //这个代码呢会一直的循环下去
    //这里的问题的原因呢是：因为编译器的优化，导致我们while循环的时候呢，因为很快，但是输入是对于while是很慢的，导致我们不会在内存中再读值
    //会直接到 寄存器中读取值
    private static  int flag = 0;
    public static void main1(String[] args) {
        Thread t1 = new Thread(() -> {
            //线程读取
           while(flag == 0) {

           }
            System.out.println("t1线程结束");
        });

        Thread t2 = new Thread(() -> {
            //线程修改
            Scanner scanner = new Scanner(System.in);
            System.out.println("修改 flag 的值为：");
            flag = scanner.nextInt();
        });

        t1.start();
        t2.start();
    }

    private static  int flag1 = 0;
    public static void main2(String[] args) {
        Thread t1 = new Thread(() -> {
            //线程读取
            while(flag1 == 0) {
                //我们可以睡眠等待修改
                try {
                    Thread.sleep(1);//尽管是 1 都可以
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("t1线程结束");
        });

        Thread t2 = new Thread(() -> {
            //线程修改
            Scanner scanner = new Scanner(System.in);
            System.out.println("修改 flag 的值为：");
            flag1 = scanner.nextInt();
        });

        t1.start();
        t2.start();
    }


    //对于 一个线程进行修改，一个线程进行等待这个因为 编译器优化的问题导致的BUG 称之为 内存可见性 问题，
    // 虽然可以添加 sleep 来解决，但是不能每次都使用 sleep 解决
    //所以我们使用 —— volatile 关键字来修饰变量，来解决 内存可见性的问题
    private volatile static int flag2 = 0;
    public static void main3(String[] args) {
        Thread t1 = new Thread(() -> {
           while(flag2 == 0) {

           }
            System.out.println("t1 线程结束");
        });
        Thread t2 = new Thread(() -> {
           Scanner scanner = new Scanner(System.in);
           System.out.println("请输入 flag 修改后的值：");
           flag2 = scanner.nextInt();
        });

        t1.start();
        t2.start();
    }


    //对于这个 volatile 这个关键词解决的 由内存可见性引起的——线程安全问题
    //而如果我们使用这个 关键词来解决 别的原因而引起的线程安全问题呢是不能够解决的，我们来举一个例子：上面的 多个线程同时修改一个变量
    private volatile static int count = 0;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                count++;
            }
            System.out.println("t1 结束");
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                count++;
            }
            System.out.println("t2 结束");
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println(count);
    }
}
